#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>

#define LISTENED_MAX_QUEUELEN 10

typedef struct ClientInfo {
    pthread_t pid;
    int socket;
    int clientNum;
    int isStarted;
} ClientInfo;

static int s_socket = -1;
static ClientInfo s_clients[LISTENED_MAX_QUEUELEN];

void runCmd(int socket, char* cmd);

void initSocket()
{
    memset(s_clients, 0, sizeof(s_clients));
    s_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (0 > s_socket) {
        printf("create socket failed(%d)!\n", errno);
        return;
    }

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(struct sockaddr_in));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(30000);
    addr.sin_addr.s_addr = INADDR_ANY;
    int bd = bind(s_socket, (struct sockaddr*)&addr, sizeof(struct sockaddr));
    if (0 > bd) {
        printf("bind failed(%d)!\n", errno);
        return;
    }

    printf("################# listening......!\n");
    int ret = listen(s_socket, LISTENED_MAX_QUEUELEN);
    if (0 > ret) {
        printf("listen failed(%d)!\n", errno);
        return;
    }
}

void finalSocket()
{
    close(s_socket);
}

void* receiveThread(void* arg);

int main(int argc, char* argv[])
{
    initSocket();

    int clientNum = 0;

    for (;;) {
        printf("################# accepting......!\n");
        struct sockaddr_in addr;
        memset(&addr, 0, sizeof(struct sockaddr_in));
        int addrLen = sizeof(struct sockaddr);
        s_clients[clientNum].socket = accept(s_socket, (struct sockaddr*)&addr, (socklen_t*)&addrLen);
        if (0 > s_clients[clientNum].socket) {
            printf("accept failed(%d), when client(%d) connect!\n", errno, clientNum);
            break;
        }
        printf("accepted!\n");

        pthread_t pid;
        s_clients[clientNum].clientNum = clientNum;
        int ret = pthread_create(&pid, NULL, receiveThread, (void*)&s_clients[clientNum]);
        if (0 != ret) {
            printf("create client(%d) thread failed!\n", clientNum);
            continue;
        }

        s_clients[clientNum].pid = pid;
        s_clients[clientNum].isStarted = 1;

        clientNum++;
    }

    finalSocket();
    return 0;
}

void* receiveThread(void* arg)
{
    if (NULL == arg) {
        return NULL;
    }

    ClientInfo* client = (ClientInfo*)arg;
    int recved = 0;

    char buf[1024];
    for (;;) {

        memset(buf, 0, sizeof(buf));

        recved = recv(client->socket, buf, 1024, 0);
        if (0 > recved) {
            printf("receive nothing!\n");
        }
        else if (0 == recved) {
            printf("client(%d) is exit!\n", client->clientNum);
            client->isStarted = 0;
            break;
        }
        else {
            printf("from client(%d) receive %d byte!\n", client->clientNum, recved);
            printf("buf : %s!\n", buf);
            runCmd(client->socket, buf);
        }
    }
    return (void*)0;
}

void runCmd(int socket, char* cmd)
{
	char buf[1024];
	int readbyte = -1;

    FILE* file = popen(cmd, "r");
    while(1) {
    	memset(buf, 0, sizeof(buf));

        fgets(buf, 1024, file);
        readbyte = strlen(buf);

        printf("readbyte is %d!\n", readbyte);

        if (0 >= readbyte) {
        	send(socket, "\n", 1, 0);
        	break;
        }
        else {
        	int sended = send(socket, buf, readbyte, 0);
        	printf("sending!\n");

        	if (0 >= sended) {
        		printf("send failed!\n");
        	}
        }
    }
    pclose(file);
}
